package com.wxtech.heartbeat;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.wxtech.heartbeat.model.Device;
import com.wxtech.heartbeat.util.CHexConver;



public class Config {
	private final String path = "config.xml";

    private final Properties properties = new Properties();
    
    private final Map<String, Object> cache = new HashMap<String, Object>();
    
    private Map<String, Device> devices = Collections.synchronizedMap(new HashMap<String, Device>());

    private boolean useEnvironmentVariables;

    void load(String file) throws IOException {
        Properties mainProperties = new Properties();
        if (file == null || file.length() == 0)
        	file = path;
        mainProperties.loadFromXML(Thread.currentThread().getContextClassLoader().getResourceAsStream(file));
        
        String defaultConfigFile = mainProperties.getProperty("config.default");
        if (defaultConfigFile != null) {
        	InputStream inputStream = null;
            inputStream = new FileInputStream(defaultConfigFile);
            properties.loadFromXML(inputStream);
        }

        properties.putAll(mainProperties); // override defaults

        useEnvironmentVariables = Boolean.parseBoolean(System.getenv("CONFIG_USE_ENVIRONMENT_VARIABLES"))
                || Boolean.parseBoolean(properties.getProperty("config.useEnvironmentVariables"));
    }

    public boolean hasKey(String key) {
        return useEnvironmentVariables && System.getenv().containsKey(getEnvironmentVariableName(key))
                || properties.containsKey(key);
    }

    public String getString(String key) {
        if (useEnvironmentVariables) {
            String value = System.getenv(getEnvironmentVariableName(key));
            if (value != null && !value.isEmpty()) {
                return value;
            }
        }
        return properties.getProperty(key);
    }

    public String getString(String key, String defaultValue) {
        return hasKey(key) ? getString(key) : defaultValue;
    }

    public boolean getBoolean(String key) {
        return Boolean.parseBoolean(getString(key));
    }

    public int getInteger(String key) {
        return getInteger(key, 0);
    }

    public int getInteger(String key, int defaultValue) {
        return hasKey(key) ? Integer.parseInt(getString(key)) : defaultValue;
    }

    public long getLong(String key) {
        return getLong(key, 0);
    }

    public long getLong(String key, long defaultValue) {
        return hasKey(key) ? Long.parseLong(getString(key)) : defaultValue;
    }

    public double getDouble(String key) {
        return getDouble(key, 0.0);
    }
    
    public double getDouble(String key, double defaultValue) {
        return hasKey(key) ? Double.parseDouble(getString(key)) : defaultValue;
    }

    public byte[] getBytes(String key) {
    	byte[] bytes = CHexConver.hexStr2Bytes(getString(key));    	    	
    	return bytes;
    }
    
    public byte getByte(String key) {
    	byte[] bytes = CHexConver.hexStr2Bytes(getString(key));    	    	
    	return bytes[0];
    }
    
    public Object getObjectInCache(String key) {
    	return cache.get(key);
    }
    
    public void setObjectInCache(String key, Object obj) {
    	cache.put(key, obj);
    }

    public static String getEnvironmentVariableName(String key) {
        return key.replaceAll("\\.", "_").replaceAll("(\\p{Lu})", "_$1").toUpperCase();
    } 
    
    public Map<String, Device> getDevices() {
    	return this.devices;
    }
}
